/**
 * 2017年4月30日
 */
package cn.edu.bjtu.entity.impl;

import java.io.InputStream;
import java.net.URI;
import java.util.concurrent.locks.ReadWriteLock;

import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClientBuilder;

import com.fasterxml.jackson.databind.ObjectMapper;

import cn.edu.bjtu.entity.ExecuteContext;
import cn.edu.bjtu.entity.ViewRenderExecuteResult;

/**
 * 这个类是同步发送http请求的基类
 * 
 * 这个关于HTTPCLIENT线程安全问题还没完全弄明白
 * 弄明白了之后在改这个类.
 * 这个 方法是同步执行的.会阻塞tomcat http处理请求
 * @author Alex
 *
 */
public abstract class BaseSimpleContext<R> implements ExecuteContext,ViewRenderExecuteResult<R>{
	public static final String METHOD_GET = "get";
	public static final String METHOD_POST = "post";
	
	protected static final ObjectMapper om = new ObjectMapper();
	
	
	boolean executing = false;
	boolean async = false;
	boolean failed = false;
	
	ReadWriteLock lock; 
	
	
	protected String msg = null;
	//30s;
//	private SocketConfig sc = SocketConfig.custom().setSoTimeout(1000*30).build();
	
	private HttpClientBuilder dhb = HttpClientBuilder.create();//.setDefaultSocketConfig(sc);
	
	/**
	 * 
	 */
	public BaseSimpleContext(ReadWriteLock lock) {
		this.lock = lock;
		om.enableDefaultTyping();
		
	}
	
	public String getMethod(){
		return METHOD_GET;
	}
	
	public abstract URI getURI();
	public abstract String getHostname();
	/**
	 * 子类重写这个方法不要在里面处理异常,直接将异常抛出,这样页面才可以正常显示错误提示.
	 * 如果要自己处理异常请设置正确的提示信息.
	 * @param in
	 * @param entity
	 * @throws Exception
	 */
	protected abstract void handleResponseInputStream(InputStream in,HttpEntity entity) throws Exception;
	public  HttpEntity getPostEntity(){
		return null;
	}
	
	public int getPort(){
		return 8080;
	}
	public HttpClient getClient(){
		return dhb.build();
	}

	public void fire(){
		this.executing = true;
		this.failed = false;
		
		HttpClient hc = getClient();
		HttpRequest hr = null;
		HttpHost hh =  new HttpHost(getHostname(), getPort());
		HttpResponse response = null;
		switch(getMethod()){
		case METHOD_GET:
			hr = new HttpGet(getURI());
			break;
		case METHOD_POST:
			hr = new HttpPost(getURI());
			((HttpPost)hr).setEntity(getPostEntity());
			break;
		default:
			hr = new HttpGet(getURI());
		}
		try {
			System.out.println(Thread.currentThread()+"要获取读锁");
		    this.lock.readLock().lock();
		    System.out.println(Thread.currentThread()+"已经获取读锁");
		    System.out.println("访问的URL"+getHostname()+" "+getURI().toString());
			response = hc.execute(hh,hr);
			HttpEntity entity = response.getEntity();
			InputStream in = entity.getContent();
			//所有重写这个方法的子类都不要自己处理异常了，直接抛出，让这里的 CATCH 来完成处理，并设置相应的标志位。
			handleResponseInputStream(in,entity);
			this.failed = false;
		} catch (Exception  e) {
			e.printStackTrace();
			this.failed = true;
			msg = e.getMessage();
		}finally{
			this.executing = false;
			System.out.println(Thread.currentThread()+"要释放读锁");
			this.lock.readLock().unlock();
			System.out.println(Thread.currentThread()+"已经释放读锁");
		}
	}
	

	@Override
	public boolean isNoCache() {
		return true;
	}

	@Override
	public String getInputDir() {
		return null;
	}

	@Override
	public String getOutPutDir() {
		return null;
	}

	@Override
	public boolean isAsync() {
		return async;
	}
	
	@Override
	public boolean isExist() {
		return true;
	}

	@Override
	public boolean isSuccess() {
		return !failed;
	}

	@Override
	public boolean isFailed() {
		return failed;
	}

	@Override
	public String getTipMessage() {
		return msg;
	}
	
	@Override
	public boolean isExecuting() {
		return executing;
	}
}
